﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection.Metadata;
using System.Security.Cryptography;
using System.Text;

namespace IntegratedMeasuring.Utils;

public static class CommonUtil
{
    public static string ComputeMd5Hash(string rawData)
    {
        using (MD5 md5Hash = MD5.Create())
        {
            byte[] bytes = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                builder.Append(bytes[i].ToString("x2"));
            }
            return builder.ToString();
        }
    }
    /// <summary>
    /// E 类型字符串 转 Demical 若数值太大，则返回0；.
    /// </summary>
    /// <param name="value">.</param>
    /// <returns>.</returns>
    public static decimal FromEDataToDecimal(this string value)
    {
        decimal.TryParse(value, System.Globalization.NumberStyles.Float, null, out decimal i);
        return i;
    }
    
    public static string KeepPlaces2(this decimal value, int places)
    {
        return value.ToString($"F{places}");
    }
    
    
    public static string RemoveSpaces(this string origin)
    {
        return origin.Replace(" ", "");
    }
    /// <summary>
    /// 移除结尾字符串.
    /// </summary>
    /// <param name="origin">.</param>
    /// <param name="terminatedStr">.</param>
    /// <returns>.</returns>
    public static string RemoveEndWith(this string origin, string terminatedStr)
    {
        if (origin.EndsWith(terminatedStr))
        {
            origin = origin.Remove(origin.LastIndexOf(terminatedStr), terminatedStr.Length);
        }

        return origin;
    }
    
    public static List<string> SplitAndIgnoreEmpty(this string val, string splitStr)
    {
        if (string.IsNullOrEmpty(val))
        {
            return new List<string>();
        }
        return val.Split(new string[] { splitStr }, StringSplitOptions.None).ToList().Where(s => !string.IsNullOrEmpty(s)).ToList();
    }
    
    public static byte[] GetBytesByLength(this byte[] bytes, int start, int length)
    {
        var vals = new List<byte>();
        for (int i = start; i < start + length; i++)
        {
            vals.Add(bytes[i]);
        }
        return vals.ToArray();
    }
    public static byte[] GetBytes(this byte[] bytes, int start, int end)
    {
        var vals = new List<byte>();
        for (int i = start; i < end; i++)
        {
            vals.Add(bytes[i]);
        }
        return vals.ToArray();
    }
    
    /// <summary>
    /// object 转 int 为空则返回0.
    /// </summary>
    /// <param name="val">值.</param>
    /// <returns>.</returns>
    public static int ToInt(this object val)
    {
        var result = 0;
        if (Convert.IsDBNull(val) || val is null)
        {
            return result;
        }

        if (val.ToString().Trim().Length > 0)
        {
            try
            {
                var temp = Convert.ToInt64(val).ToString();
                int.TryParse(temp, out result);
            }
            catch (Exception ex)
            {
                // GI._logger.Error(ex, $"object -> int 异常");
            }
        }
        return result;
    }
    
    public static float ToFloat(this byte[] datas)
    {
        if (datas.Length != 4)
        {
            return 0.0f;
        }

        return BitConverter.ToSingle(datas, 0);
    }
    
    public static double UnitConversion(this float val, double num)
    {
        return val * num;
    }
    
    public static string KeepPlaces2(this double value, int places)
    {
        return value.ToString($"F{places}");
    }
    
    /// <summary>
    /// The KeepPlaces.
    /// </summary>
    /// <param name="value">The value<see cref="float"/>.</param>
    /// <param name="places">The places<see cref="int"/>.</param>
    /// <returns>The <see cref="float"/>.</returns>
    public static string KeepPlaces2(this float value, int places)
    {
        return value.ToString($"F{places}");
    }
    
    public static void OhmUnitConversion(this float val, IntegratedMeasuring.ViewModels.Entity.GC.OhmUnit startUnit, out string valWithUnit)
        {
            valWithUnit = string.Empty;
            List<IntegratedMeasuring.ViewModels.Entity.GC.OhmUnit> units = Enum.GetValues(typeof(IntegratedMeasuring.ViewModels.Entity.GC.OhmUnit)).Cast<IntegratedMeasuring.ViewModels.Entity.GC.OhmUnit>().ToList();
            int unitIndex = units.FindIndex(s => s == startUnit);
            if (unitIndex == -1) return;

            float temp = val;
            try
            {
                if (temp < 1)
                {
                    if (unitIndex == 0)
                    {
                        return;
                    }
                    temp = temp * 1000.0f;
                    if (temp < 1000 && temp > 0.01)
                    {
                        unitIndex--;
                        return;
                    }
                    if (unitIndex + 1 == 1)
                    {
                        return;
                    }
                    unitIndex--;
                    temp = temp * 1000.0f;
                    if (temp < 1000 && temp > 0.01)
                    {
                        unitIndex--;
                        return;
                    }

                    if (unitIndex + 1 == 1)
                    {
                        return;
                    }
                    unitIndex--;
                }
                else
                {
                    if (temp < 1000)
                    {
                        return;
                    }

                    temp = temp / 1000.0f;
                    if (temp < 1000)
                    {
                        unitIndex++;
                        return;
                    }

                    if (unitIndex + 1 == units.Count)
                    {
                        return;
                    }
                    unitIndex++;
                    temp = temp / 1000.0f;
                    if (temp < 1000)
                    {
                        unitIndex++;
                        return;
                    }

                    if (unitIndex + 1 == units.Count)
                    {
                        return;
                    }
                    unitIndex++;
                }
            }
            finally
            {
                valWithUnit = $"{temp.KeepPlaces2(3)}({units[unitIndex].ToString()})";
            }

        }
    
    public static void HenryUnitConversion(this float val, IntegratedMeasuring.ViewModels.Entity.GC.HenryUnit startUnit, out string valWithUnit)
        {
            valWithUnit = string.Empty;
            List<IntegratedMeasuring.ViewModels.Entity.GC.HenryUnit> units = Enum.GetValues(typeof(IntegratedMeasuring.ViewModels.Entity.GC.HenryUnit)).Cast<IntegratedMeasuring.ViewModels.Entity.GC.HenryUnit>().ToList();
            int unitIndex = units.FindIndex(s => s == startUnit);
            if (unitIndex == -1) return;

            float temp = val;
            try
            {
                if (temp < 1)
                {
                    if (unitIndex == 0)
                    {
                        return;
                    }
                    temp = temp * 1000.0f;
                    if (temp < 1000 && temp > 0.01)
                    {
                        unitIndex--;
                        return;
                    }
                    if (unitIndex + 1 == 1)
                    {
                        return;
                    }
                    unitIndex--;
                    temp = temp * 1000.0f;
                    if (temp < 1000 && temp > 0.01)
                    {
                        unitIndex--;
                        return;
                    }

                    if (unitIndex + 1 == 1)
                    {
                        return;
                    }
                    unitIndex--;
                }
                else
                {
                    if (temp < 1000)
                    {
                        return;
                    }

                    temp = temp / 1000.0f;
                    if (temp < 1000)
                    {
                        unitIndex++;
                        return;
                    }

                    if (unitIndex + 1 == units.Count)
                    {
                        return;
                    }
                    unitIndex++;
                    temp = temp / 1000.0f;
                    if (temp < 1000)
                    {
                        unitIndex++;
                        return;
                    }

                    if (unitIndex + 1 == units.Count)
                    {
                        return;
                    }
                    unitIndex++;
                }
            }
            finally
            {
                valWithUnit = $"{temp.KeepPlaces2(3)}({units[unitIndex].ToString()})";
            }

        }
    
    public static DateTime ToDateTime(this object val)
    {
        var result = DateTime.Now;
        if (Convert.IsDBNull(val) || val is null)
        {
            return result;
        }

        if (val.ToString().Trim().Length > 0)
        {
            DateTime.TryParse(val.ToString(), out result);
        }

        return result;
    }
    
    public static double ConvertScientificNotationToDouble(string scientificNotation)
    {
        if (double.TryParse(scientificNotation, NumberStyles.Float | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out double result))
        {
            return result;
        }
        else
        {
            throw new FormatException("输入的字符串不是有效的科学计数法格式。");
        }
    }
    
    // 电阻单位转换
    public static string[] FormatResistance(double value, string unit)
    {
        // 定义单位转换系数
        var unitFactors = new Dictionary<string, double>
        {
            {"nΩ", 1e-9},
            {"µΩ", 1e-6},
            {"mΩ", 1e-3},
            {"Ω", 1},
            {"kΩ", 1e3},
            {"MΩ", 1e6},
            {"GΩ", 1e9}
        };
 
        // 检查单位是否有效
        if (!unitFactors.ContainsKey(unit))
        {
            throw new ArgumentException("无效的单位", nameof(unit));
        }
 
        // 将电阻值转换为欧姆
        double ohms = value * unitFactors[unit];
 
        // 根据欧姆值的大小选择保留的小数位数和单位
        string formattedValue;
        string finalUnit;
 
        if (Math.Abs(ohms) >= 1e9)
        {
            formattedValue = (ohms / 1e9).ToString("F3"); // GΩ，不保留小数
            finalUnit = "GΩ";
        }
        else if (Math.Abs(ohms) >= 1e6)
        {
            formattedValue = (ohms / 1e6).ToString("F3"); // MΩ，保留一位小数
            finalUnit = "MΩ";
        }
        else if (Math.Abs(ohms) >= 1e3)
        {
            formattedValue = (ohms / 1e3).ToString("F3"); // kΩ，保留两位小数
            finalUnit = "kΩ";
        }
        else if (Math.Abs(ohms) < 1 && Math.Abs(ohms) >= 1e-3)
        {
            formattedValue = (ohms * 1e3).ToString("F3"); // mΩ，保留两位小数
            finalUnit = "mΩ";
        }
        else if (Math.Abs(ohms) < 1e-3 && Math.Abs(ohms) >= 1e-6)
        {
            formattedValue = (ohms * 1e6).ToString("F3"); // µΩ，保留三位小数
            finalUnit = "µΩ";
        }
        else if (Math.Abs(ohms) < 1e-6)
        {
            formattedValue = (ohms * 1e9).ToString("F3"); // nΩ，保留六位小数
            finalUnit = "nΩ";
        }
        else
        {
            formattedValue = ohms.ToString("F3"); // Ω，对于1以下的值保留三位小数，虽然通常Ω不会小于1但这里为了完整性
            finalUnit = "Ω";
        }
 
        // 去除末尾不必要的零
        if (formattedValue.Contains('.'))
        {
            formattedValue = formattedValue.TrimEnd('0').TrimEnd('.');
        }
 
        // 如果结果为科学计数法，则转换为普通表示法（可选，根据需要）
        // 注意：这一步可能会增加字符串长度，因此仅在需要时启用
        // formattedValue = double.Parse(formattedValue).ToString(CultureInfo.InvariantCulture);
 
        // 返回结果数组
        return new string[] { formattedValue, finalUnit };
    }
    
    // 电流单位转换
    public static string[] FormatCurrent(double value, string unit)
    {
        // 定义单位转换系数
        var unitFactors = new Dictionary<string, double>
        {
            {"nA", 1e-9},
            {"µA", 1e-6},
            {"mA", 1e-3},
            {"A", 1},
            {"kA", 1e3},
            {"MA", 1e6},
            {"GA", 1e9}
        };
 
        // 检查单位是否有效
        if (!unitFactors.ContainsKey(unit))
        {
            throw new ArgumentException("无效的单位", nameof(unit));
        }
 
        // 将电阻值转换为欧姆
        double ohms = value * unitFactors[unit];
 
        // 根据欧姆值的大小选择保留的小数位数和单位
        string formattedValue;
        string finalUnit;
 
        if (Math.Abs(ohms) >= 1e9)
        {
            formattedValue = (ohms / 1e9).ToString("F3"); // GA，不保留小数
            finalUnit = "GA";
        }
        else if (Math.Abs(ohms) >= 1e6)
        {
            formattedValue = (ohms / 1e6).ToString("F3"); // MA，保留一位小数
            finalUnit = "MA";
        }
        else if (Math.Abs(ohms) >= 1e3)
        {
            formattedValue = (ohms / 1e3).ToString("F3"); // kA，保留两位小数
            finalUnit = "kA";
        }
        else if (Math.Abs(ohms) < 1 && Math.Abs(ohms) >= 1e-3)
        {
            formattedValue = (ohms * 1e3).ToString("F3"); // mA，保留两位小数
            finalUnit = "mA";
        }
        else if (Math.Abs(ohms) < 1e-3 && Math.Abs(ohms) >= 1e-6)
        {
            formattedValue = (ohms * 1e6).ToString("F3"); // µA，保留三位小数
            finalUnit = "µA";
        }
        else if (Math.Abs(ohms) < 1e-6)
        {
            formattedValue = (ohms * 1e9).ToString("F3"); // nA，保留六位小数
            finalUnit = "nA";
        }
        else
        {
            formattedValue = ohms.ToString("F3");
            finalUnit = "A";
        }
 
        // 去除末尾不必要的零
        if (formattedValue.Contains('.'))
        {
            formattedValue = formattedValue.TrimEnd('0').TrimEnd('.');
        }
 
        // 如果结果为科学计数法，则转换为普通表示法（可选，根据需要）
        // 注意：这一步可能会增加字符串长度，因此仅在需要时启用
        // formattedValue = double.Parse(formattedValue).ToString(CultureInfo.InvariantCulture);
 
        // 返回结果数组
        return new string[] { formattedValue, finalUnit };
    }
    
    // 电容单位转换
    public static string[] FormatCapacitance(double value, string unit)
    {
        // 定义单位转换系数
        var unitFactors = new Dictionary<string, double>
        {
            { "pF", 1e-12 },
            { "nF", 1e-9 },
            { "µF", 1e-6 },
            { "mF", 1e-3 },
            { "F", 1 },
            { "kF", 1e3 },
            { "MF", 1e6 },
            { "GF", 1e9 }
        };
        // 检查单位是否有效
        if (!unitFactors.ContainsKey(unit))
        {
            throw new ArgumentException("无效的单位", nameof(unit));
        }
        // 将电容值转换为法尔
        double ohms = value * unitFactors[unit];
        
        // 根据电容值的大小选择保留的小数位数和单位
        string formattedValue;
        string finalUnit;
 
        if (Math.Abs(ohms) >= 1e9)
        {
            formattedValue = (ohms / 1e9).ToString("F3"); // GF，不保留小数
            finalUnit = "GF";
        }
        else if (Math.Abs(ohms) >= 1e6)
        {
            formattedValue = (ohms / 1e6).ToString("F3"); // MF，保留一位小数
            finalUnit = "MF";
        }
        else if (Math.Abs(ohms) >= 1e3)
        {
            formattedValue = (ohms / 1e3).ToString("F3"); // kF，保留两位小数
            finalUnit = "kF";
        }
        else if (Math.Abs(ohms) < 1 && Math.Abs(ohms) >= 1e-3)
        {
            formattedValue = (ohms * 1e3).ToString("F3"); // mF，保留两位小数
            finalUnit = "mF";
        }
        else if (Math.Abs(ohms) < 1e-3 && Math.Abs(ohms) >= 1e-6)
        {
            formattedValue = (ohms * 1e6).ToString("F3"); // µF，保留三位小数
            finalUnit = "µF";
        }
        else if (Math.Abs(ohms) < 1e-6 && Math.Abs(ohms) >= 1e-9)
        {
            formattedValue = (ohms * 1e9).ToString("F3"); // nF，保留六位小数
            finalUnit = "nF";
        }
        else if (Math.Abs(ohms) < 1e-9)
        {
            formattedValue = (ohms * 1e12).ToString("F3"); // nF，保留六位小数
            finalUnit = "pF";
        }
        else
        {
            formattedValue = ohms.ToString("F3"); // F，对于1以下的值保留三位小数，虽然通常F不会小于1但这里为了完整性
            finalUnit = "F";
        }
 
        // 去除末尾不必要的零
        if (formattedValue.Contains('.'))
        {
            formattedValue = formattedValue.TrimEnd('0').TrimEnd('.');
        }
        
        // 如果结果为科学计数法，则转换为普通表示法（可选，根据需要）
        // 注意：这一步可能会增加字符串长度，因此仅在需要时启用
        // formattedValue = double.Parse(formattedValue).ToString(CultureInfo.InvariantCulture);
 
        // 返回结果数组
        return new string[] { formattedValue, finalUnit };
    }
    
    // 电感应单位转换
    public static string[] FormatInductance(double value, string unit)
    {
        // 定义单位转换系数
        var unitFactors = new Dictionary<string, double>
        {
            {"nH", 1e-9},
            {"µH", 1e-6},
            {"mH", 1e-3},
            {"H", 1},
            {"kH", 1e3},
            {"MH", 1e6},
            {"GH", 1e9}
        };
 
        // 检查单位是否有效
        if (!unitFactors.ContainsKey(unit))
        {
            throw new ArgumentException("无效的单位", nameof(unit));
        }
 
        // 将电阻值转换为欧姆
        double ohms = value * unitFactors[unit];
 
        // 根据欧姆值的大小选择保留的小数位数和单位
        string formattedValue;
        string finalUnit;
 
        if (Math.Abs(ohms) >= 1e9)
        {
            formattedValue = (ohms / 1e9).ToString("F3"); // GH，不保留小数
            finalUnit = "GH";
        }
        else if (Math.Abs(ohms) >= 1e6)
        {
            formattedValue = (ohms / 1e6).ToString("F3"); // MH，保留一位小数
            finalUnit = "MH";
        }
        else if (Math.Abs(ohms) >= 1e3)
        {
            formattedValue = (ohms / 1e3).ToString("F3"); // kH，保留两位小数
            finalUnit = "kH";
        }
        else if (Math.Abs(ohms) < 1 && Math.Abs(ohms) >= 1e-3)
        {
            formattedValue = (ohms * 1e3).ToString("F3"); // mH，保留两位小数
            finalUnit = "mH";
        }
        else if (Math.Abs(ohms) < 1e-3 && Math.Abs(ohms) >= 1e-6)
        {
            formattedValue = (ohms * 1e6).ToString("F3"); // µH，保留三位小数
            finalUnit = "µH";
        }
        else if (Math.Abs(ohms) < 1e-6)
        {
            formattedValue = (ohms * 1e9).ToString("F3"); // nH，保留六位小数
            finalUnit = "nH";
        }
        else
        {
            formattedValue = ohms.ToString("F3"); // H，对于1以下的值保留三位小数，虽然通常H不会小于1但这里为了完整性
            finalUnit = "H";
        }
 
        // 去除末尾不必要的零
        if (formattedValue.Contains('.'))
        {
            formattedValue = formattedValue.TrimEnd('0').TrimEnd('.');
        }
        
        // 如果结果为科学计数法，则转换为普通表示法（可选，根据需要）
        // 注意：这一步可能会增加字符串长度，因此仅在需要时启用
        // formattedValue = double.Parse(formattedValue).ToString(CultureInfo.InvariantCulture);
 
        // 返回结果数组
        return new string[] { formattedValue, finalUnit };
    }
    
    // 获取现在是今年的第几周
    public static int GetWeekOfYear(DateTime date)
    {
        Calendar calendar = CultureInfo.CurrentCulture.Calendar;
 
        // 获取当前日期是今年的第几周（ISO 8601标准）
        // CalendarWeekRule.FirstFourDayWeek 表示一周的第一天是星期一到星期四中的某一天，且该周包含该年的第一个星期四
        // DayOfWeek.Monday 表示一周的第一天是星期一
        CalendarWeekRule calendarWeekRule = CalendarWeekRule.FirstFourDayWeek;
        DayOfWeek firstDayOfWeek = DayOfWeek.Monday;
 
        return calendar.GetWeekOfYear(date, calendarWeekRule, firstDayOfWeek);
    }
    
    // 获取本周的周一的一天中开始的时间
    public static DateTime GetMondayOfThisWeek()
    {
        // 获取当前日期和时间
        DateTime now = DateTime.Now;
        
        // 计算本周周一的日期
        // 先获取今天是周几，然后计算与周一的差值
        int daysUntilMonday = (7 + (int)now.DayOfWeek - (int)DayOfWeek.Monday) % 7;
        DateTime monday = now.AddDays(-daysUntilMonday);
        
        // 获取周一的开始时间（午夜00:00:00）
        DateTime mondayStartTime = monday.Date; // .Date属性会返回一个新的DateTime对象，其时间部分被设置为午夜

        return mondayStartTime;
    }
    
    public static byte[] Append(this byte[] bytes, byte[] appends)
    {
        byte[] vals = new byte[bytes.Length + appends.Length];
        for (int i = 0; i < bytes.Length; i++)
        {
            vals[i] = bytes[i];
        }
        for (int j = 0; j < appends.Length; j++)
        {
            vals[bytes.Length + j] = appends[j];
        }
        return vals;
    }
}
